/*
 * Copyright the original author or authors.
 *
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.mozilla.org/MPL/MPL-1.1.html *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Authors:
 *   Russell Weir damonsbane/gmail dot com
 */
package hxbase.flash.net;
import hxbase.events.Event;
import hxbase.flash.events.EventTypes;
import hxbase.flash.IFlashWrapper;

class NetConnectionEvents extends EventGroup {
	var onNetStatus	: Event<Dynamic->Void>;
	var onAsyncError : Event<Dynamic->Void>;
	var onIoError : Event<Dynamic->Void>;
	var onSecurityError : Event<Dynamic->Void>;

	override private function init() {
		onNetStatus = new Event<Dynamic->Void>(this);
		onAsyncError = new Event<Dynamic->Void>(this);
		onIoError = new Event<Dynamic->Void>(this);
		onSecurityError = new Event<Dynamic->Void>(this);
	}
}

class NetConnection
	extends hxbase.flash.events.EventDispatcher<NetConnectionEvents>,
#if flash9
	implements IFlashWrapper<flash.net.NetConnection>
#else flash
	implements IFlashWrapper<flash.NetConnection>
#end
{
	/**
	Indicates the object on which callback methods should be invoked. The default is this NetConnection instance. If you set the client property to another object, callback methods will be invoked on that object.
	*/
	public var client(getClient, setClient) :Dynamic;
	public var connected(getConnected, null) : Bool;
	public var isConnected(getConnected, null) : Bool;
	public var connectedProxyType(getConnectedProxyType, null) : String;
	public var proxyType(getProxyType,setProxyType) : String;
	public var uri(getUri,null) : String;
#if flash9
	var nc : flash.net.NetConnection;
#else flash
	var nc : flash.NetConnection;
#end

	public function new() {
		super();
		events = new NetConnectionEvents();
#if flash9
		nc = new flash.net.NetConnection();
		//nc.addEventListener(flash.events.NetStatusEvent.NET_STATUS,onNetStatus);
		//nc.addEventListener(flash.events.AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
		//nc.addEventListener(flash.events.IOErrorEvent.IO_ERROR, onIoError);
		//nc.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

#else flash
		nc = new flash.NetConnection();
		nc.onStatus = onNetStatus;
		nc.onResult = onResult;
#end
	}

	/**
		Create an hxbase NetConnection from an existing flash or
		flash9 NetConnection
	*/
#if flash9
	public static function fromNetConnection(pNc :flash.net.NetConnection ) {
#else flash
	public static function fromNetConnection(pNc :flash.NetConnection ) {
#end
		var nc = new NetConnection();
		nc.nc = pNc;
		return nc;
	}

	public function getConnected() {
#if flash9
		return nc.connected;
#else flash
		return nc.isConnected;
#end
	}

	/**
	If a successful connection is made, indicates the method that was used to make it: a direct connection, the CONNECT method, or HTTP tunneling.
	"none", "HTTP", "HTTPS", and "CONNECT".
	*/
	public function getConnectedProxyType() {
#if flash9
		return nc.connectedProxyType;
#else flash
		// todo
		return "none";
#end
	}

	public function getProxyType() {
#if flash9
		return nc.proxyType;
#end
	}

	public function setProxyType(s) {
#if flash9
		nc.proxyType = s;
		return s;
#end
	}

	public function getClient() : Dynamic {
#if flash9
		return nc.client;
#else
		todo
#end
	}

	public function setClient(c : Dynamic) : Dynamic {
#if flash9
		nc.client = c;
		return nc.client;
#else
		todo
#end
	}

	// flash9 allows one less parameter than flash
	public function call(command : String, responder : Responder, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void {
		nc.call(command, responder.getObject(),p1,p2,p3,p4,p5);
	}

	public function getUri() : String {
		return nc.uri;
	}

	// flash < 9 allows one less ?p
	public function connect(uri : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic) {
		nc.connect(uri,p1,p2,p3,p4);
	}

	public function close() : Void {
		nc.close();
	}

	function onNetStatus(e) {
		//if( e.info.code == "NetConnection.Connect.Success" )
		// NetConnection.Call.Failed
		// NetConnection.Connect.AppShutdown
		// NetConnection.Connect.Closed
		// NetConnection.Connect.Failed
		// NetConnection.Connect.Rejected
		// NetConnection.Connect.Success
		events.onNetStatus.call(e);
	}

	function onAsyncError(e:Dynamic) {}

	function onIoError(e:Dynamic) {}

	function onSecurityError(e:Dynamic) {}

	//function onResult(e:Dynamic) {}

	public function addEventListener(type :String, listener : Dynamic->Void) {
		switch(type) {
		case EventTypes.NET_STATUS:
			checkSubscribed(nc, type, onNetStatus);
			events.onNetStatus.bind(null, listener);
		case EventTypes.ASYNC_ERROR:
			checkSubscribed(nc, type, onAsyncError);
			events.onAsyncError.bind(null, listener);
		case EventTypes.IO_ERROR:
			checkSubscribed(nc, type, onIoError);
			events.onIoError.bind(null, listener);
		case EventTypes.SECURITY_ERROR:
			checkSubscribed(nc, type, onSecurityError);
			events.onSecurityError.bind(null, listener);
		default:
			trace("["+here.methodName+"] Unknown event "+type);
		}
	}

	public function getObject() {
		return nc;
	}
}